﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TimeTrak.DAL;
using System.ComponentModel;
using TimeTrak.BLL;
using System.Windows.Forms;
using System.Drawing;
using TimeTrak.Views;

namespace TimeTrak.Controllers
{

    /// <summary>
    /// The top level, core controlling class
    /// </summary>
    public class MainViewController
    {
        public MainForm MainView { get; private set; }
        public TimeEditController EditController { get; private set; }
        public MainTaskHolderThing TaskHolderThing { get; private set; }

        TimeManager tm;
        Timer uiUpdateTimer;


        DataAccess da;


        public string CurrentDataPath { get; private set; }


        int trackCheckBoxIndex;
        int doneCheckBoxIndex;
        int idIndex;
        int descriptionIndex;



        private TimeTrak.Properties.Settings Settings
        {
            get { return TimeTrak.Properties.Settings.Default; }
        }


        public MainViewController(MainForm viewForm)
        {
            try
            {
                TaskHolderThing = new MainTaskHolderThing();

                MainView = viewForm;

                //setup observation on needed view events
                MainView.OpenToolStripMenuItem.Click += new EventHandler(OpenToolStripMenuItem_Click);
                MainView.NewToolStripMenuItem.Click += new EventHandler(NewToolStripMenuItem_Click);
                MainView.AddNewTaskToolStripMenuItem.Click += new EventHandler(AddNewTaskToolStripMenuItem_Click);
                MainView.EditTaskTimeToolStripMenuItem.Click += new EventHandler(EditTaskTimeToolStripMenuItem_Click);
                MainView.DeleteTaskToolStripMenuItem.Click += new EventHandler(DeleteTaskToolStripMenuItem_Click);
                MainView.ToogleTrackingToolStripMenuItem.Click += new EventHandler(ToogleTrackingToolStripMenuItem_Click);

                MainView.AddToolStripButton.Click += new EventHandler(AddToolStripButton_Click);

                MainView.DataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(DataGridView1_CellContentClick);
                MainView.DataGridView1.CellContentDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(DataGridView1_CellContentDoubleClick);
                MainView.DataGridView1.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(DataGridView1_CellEndEdit);
                MainView.DataGridView1.CellMouseDown += new System.Windows.Forms.DataGridViewCellMouseEventHandler(DataGridView1_CellMouseDown);
                MainView.Resize += new EventHandler(View_Resize);
                MainView.FormClosed += new FormClosedEventHandler(View_FormClosed);
                MainView.NotifyIcon1.Click += new EventHandler(NotifyIcon1_Click);

                trackCheckBoxIndex = MainView.DataGridView1.Columns["Tracking"].Index;
                doneCheckBoxIndex = MainView.DataGridView1.Columns["Done"].Index;
                idIndex = MainView.DataGridView1.Columns["ID"].Index;
                descriptionIndex = MainView.DataGridView1.Columns["Description"].Index;

                MainView.DataGridView1.AutoGenerateColumns = false;

                tm = new TimeManager();
                tm.TimerTick += new TickEventHandler(tm_TimerTick);


                uiUpdateTimer = new Timer();
                uiUpdateTimer.Interval = 3000;
                uiUpdateTimer.Tick += new EventHandler(uiUpdateTimer_Tick);

                da = new DataAccess();

            }
            catch (Exception ex)
            {
                throw new Exception("Error initializing TimeTrakController!", ex);
            }

        }



        void ToogleTrackingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {

                Task item = GetSelectedTaskFromDataGrid(MainView.DataGridView1);
                int id = item.ID;
                bool currentCheckedValue = item.IsRunning;


                TaskHolderThing.SetTracking(id, !currentCheckedValue);
                this.SaveData();
                UpdateDataGridView();
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in toggleTrackingToolStripMenuItem_Click!", ex));
            }
        }

        public Task GetSelectedTaskFromDataGrid(DataGridView gridView)
        {
            int rowIndex = gridView.SelectedRows[0].Index;
            DataGridViewRow row = GetRowFromIndex(rowIndex);
            int id = GetTaskIDFromRow(row);
            Task item = TaskHolderThing.GetTask(id);
            return item;
        }

        void DeleteTaskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Task item = GetSelectedTaskFromDataGrid(MainView.DataGridView1);


                string msg = String.Format("Are you sure you want to delete the '{0}' task?", item.Description);
                if (MessageBox.Show(msg, "Delete Task", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    TaskHolderThing.DeleteTask(item.ID);
                    SaveData();
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in deleteToolStripMenuItem_Click!", ex));
            }
        }

        void EditTaskTimeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TimeEditController edit = new TimeEditController();
            Task currentTask = GetSelectedTaskFromDataGrid(MainView.DataGridView1);
            edit.Show(currentTask);
        }

        void uiUpdateTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                UpdateDataGridView();
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in uiUpdateTimer_Tick!", ex));
            }
        }

        void tm_TimerTick(object sender, System.Timers.ElapsedEventArgs e)
        {
            SaveData();
        }

        #region View Events

        void NotifyIcon1_Click(object sender, EventArgs e)
        {
            try
            {
                MainView.NotifyIcon1.Visible = false;
                MainView.Show();
                MainView.WindowState = FormWindowState.Normal;
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in notifyIcon1_Click!", ex));
            }
        }

        void View_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                SaveData();
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in MainForm_FormClosed!", ex));
            }
        }

        void View_Resize(object sender, EventArgs e)
        {
            try
            {
                if (FormWindowState.Minimized == MainView.WindowState)
                {
                    MainView.NotifyIcon1.Visible = true;
                    MainView.Hide();
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in MainForm_Resize!", ex));
            }
        }

        /// <summary>
        /// Force selection of rows when you left/right click in a row.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DataGridView1_CellMouseDown(object sender, System.Windows.Forms.DataGridViewCellMouseEventArgs e)
        {
            try
            {
                //Console.Out.WriteLine("CellMouseDown!");
                if (e.Button == MouseButtons.Right)
                {
                    if (e.RowIndex > -1)
                    {
                        MainView.DataGridView1.Rows[e.RowIndex].Selected = true;
                    }
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in dataGridView1_CellMouseDown!", ex));
            }
        }

        void DataGridView1_CellEndEdit(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.ColumnIndex != trackCheckBoxIndex)
                {
                    SaveData();
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in dataGridView1_CellEndEdit!", ex));
            }
        }

        void DataGridView1_CellContentDoubleClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
        {
            try
            {
                DataGridView1_CellContentClick(sender, e);
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in dataGridView1_CellContentDoubleClick!", ex));
            }
        }

        void DataGridView1_CellContentClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
        {
            try
            {

                //Console.Out.WriteLine("dataGridView1_CellContentClick()");
                if (e.RowIndex > -1)
                {
                    DataGridViewRow row = GetRowFromIndex(e.RowIndex);
                    int id = GetTaskIDFromRow(row);
                    if (e.ColumnIndex == trackCheckBoxIndex)
                    {
                        MainView.DataGridView1.EndEdit();
                        bool value = (bool)row.Cells[e.ColumnIndex].Value;
                        TaskHolderThing.SetTracking(id, value);
                        this.SaveData();
                        UpdateDataGridView();
                    }
                    else if (e.ColumnIndex == doneCheckBoxIndex)
                    {
                        MainView.DataGridView1.EndEdit();
                        bool value = (bool)row.Cells[e.ColumnIndex].Value;
                        SetDone(e.RowIndex, id, value);
                        UpdateDataGridView();


                    }
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in dataGridView1_CellContentClick!", ex));
            }
        }

        void AddToolStripButton_Click(object sender, EventArgs e)
        {
            try
            {
                TaskHolderThing.AddNewTask();
                UpdateDataGridView();
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in AddToolStripButton_Click!", ex));
            }
        }

        void AddNewTaskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                TaskHolderThing.AddNewTask();
                UpdateDataGridView();
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in addNewTaskToolStripMenuItem_Click!", ex));
            }
        }

        void NewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (MainView.SaveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string filePath = MainView.SaveFileDialog1.FileName;
                    CreateNewDataFile(filePath);
                    LoadDataFile(filePath);
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in newToolStripMenuItem_Click!", ex));
            }
        }

        void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (MainView.OpenFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string filePath = MainView.OpenFileDialog1.FileName;
                    LoadDataFile(filePath);
                }
            }
            catch (Exception ex)
            {
                HandleException(new Exception("Error in openToolStripMenuItem_Click!", ex));
            }

        }

        #endregion




        public void SaveData()
        {
            try
            {
                if (CurrentDataPath != null)
                {
                    TaskHolderThing.UpdateTaskTimes();
                    List<Task> tempList = TaskHolderThing.TaskList.ToList<Task>();
                    da.SaveTaskList(tempList, CurrentDataPath);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error persisting data!", ex);
            }
        }








        private void SetDone(int rowIndex, int taskID, bool value)
        {
            try
            {
                if (value == true)
                {
                    //stop tracking if its done
                    TaskHolderThing.SetTracking(taskID, false);
                    this.SaveData();

                    //disable tracking checkbox (everything else?)
                    MainView.DataGridView1.Rows[rowIndex].Cells[trackCheckBoxIndex].ReadOnly = true;

                    //strikethough description box
                    Font f1 = MainView.DataGridView1.Font;
                    Font f2 = new Font(f1, FontStyle.Strikeout);
                    MainView.DataGridView1.Rows[rowIndex].Cells[descriptionIndex].Style.Font = f2;

                }
                else
                {
                    //enable tracking checkbox (everything else?)
                    MainView.DataGridView1.Rows[rowIndex].Cells[trackCheckBoxIndex].ReadOnly = false;


                    //unstrikethrough the description box
                    Font f1 = MainView.DataGridView1.Font;
                    Font f2 = new Font(f1, FontStyle.Regular);
                    MainView.DataGridView1.Rows[rowIndex].Cells[descriptionIndex].Style.Font = f2;
                }

            }
            catch (Exception ex)
            {
                throw new Exception("Error Seting Done!", ex);
            }
        }



        internal void LoadDataFile(string filePath)
        {
            try
            {
                TaskHolderThing.TaskList = new BindingTaskList(da.GetTaskList(filePath));
                TaskHolderThing.InitTaskList();

               

                CurrentDataPath = filePath;

                tm.Start();

                MainView.DataGridView1.DataSource = TaskHolderThing.TaskList;

                UpdateDataGridView();
                uiUpdateTimer.Start();

                Settings.CurrentPathSetting = filePath;
                Settings.Save();

            }
            catch (Exception ex)
            {
                throw new Exception("Error loading data file!", ex);
            }

        }

        internal void CreateNewDataFile(string filePath)
        {
            try
            {
                da.SaveTaskList(new List<Task>(), filePath);
                LoadDataFile(filePath);
            }
            catch (Exception ex)
            {
                throw new Exception("Error creating new data file!", ex);
            }
        }

        internal void ShowView()
        {
            string path = Settings.CurrentPathSetting;
            if (path.Length > 0)
            {
                LoadDataFile(path);
            }
            Application.Run(MainView);
        }



        private DataGridViewRow GetRowFromIndex(int rowIndex)
        {
            try
            {
                DataGridViewRow row = null;
                if (rowIndex > -1)
                {
                    row = MainView.DataGridView1.Rows[rowIndex];
                }
                return row;
            }
            catch (Exception ex)
            {
                throw new Exception("Error getting row from index!", ex);
            }
        }


        private int GetTaskIDFromRow(DataGridViewRow row)
        {
            try
            {
                return (int)row.Cells[idIndex].Value;
            }
            catch (Exception ex)
            {
                throw new Exception("Error getting task ID from row!", ex);
            }
        }




        private void UpdateDataGridView()
        {
            try
            {

                Console.Out.WriteLine("Updating UI!");
                TaskHolderThing.UpdateTaskTimes();
                MainView.HoursTodayLabel.Text = TaskHolderThing.GetHoursForDate(DateTime.Today).TotalHours.ToString("N2");
                MainView.HoursWeekLabel.Text = TaskHolderThing.GetHoursWTD(DateTime.Today).TotalHours.ToString("N2");
                MainView.DataGridView1.Invalidate();
                MainView.DataGridView1.Update();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Updating UI!", ex);
            }

        }

        private void HandleException(Exception ex)
        {
            string msg = "Oh Noes! Error!\n";
            Exception ex2 = ex;
            msg += ex2.Message + "\n";
            ex2 = ex2.InnerException;
            while (ex2 != null)
            {
                msg += ex2.Message + "\n";
                ex2 = ex2.InnerException;
            }
            MessageBox.Show(msg);
        }

    }
}
